package edu.ucdavis.gwt.gis.client.print;


import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

import edu.ucdavis.cstars.client.MapWidget;
import edu.ucdavis.cstars.client.Util;
import edu.ucdavis.cstars.client.event.MapLoadHandler;
import edu.ucdavis.cstars.client.layers.ArcGISTiledMapServiceLayer;
import edu.ucdavis.cstars.client.layers.Layer;
import edu.ucdavis.cstars.client.layers.LayerInfo;
import edu.ucdavis.cstars.client.layers.OpenStreetMapLayer;
import edu.ucdavis.cstars.client.restful.LegendInfo;
import edu.ucdavis.gwt.gis.client.GisClient;
import edu.ucdavis.gwt.gis.client.DataManager;
import edu.ucdavis.gwt.gis.client.layers.DataLayer;
import edu.ucdavis.gwt.gis.client.layers.KmlDataLayer;
import edu.ucdavis.gwt.gis.client.layers.MapServerDataLayer;
import edu.ucdavis.gwt.gis.client.layers.DataLayer.DataLayerLoadHandler;
import edu.ucdavis.gwt.gis.client.layers.DataLayer.DataLayerType;
import edu.ucdavis.gwt.gis.client.layout.FeatureLayerLegendPanel;
import edu.ucdavis.gwt.gis.client.layout.LegendPanel;
import edu.ucdavis.gwt.gis.client.state.ClientStateManager;
import edu.ucdavis.gwt.gis.client.state.overlays.KmlOverlay;
import edu.ucdavis.gwt.gis.client.state.overlays.MapServerOverlay;
import edu.ucdavis.gwt.gis.client.state.overlays.MapStateOverlay;
import edu.ucdavis.gwt.gis.client.toolbar.BasemapGallery;

public abstract class PrintPage {
	
	private MapWidget map;
	private SimplePanel rootPanel;
	private Layer baseLayer;
	private SimplePanel printModePanel;
	private MapStateOverlay mapState;
	
	public interface AdditionalAttributesHandler {
		public String getAdditionalAttributes();
	};
	public AdditionalAttributesHandler handler = null;
	
	public void setAdditionalAttributeHandler(AdditionalAttributesHandler handler){
		this.handler = handler;
	}
	
	public void init(SimplePanel rp) {
		mapState = ClientStateManager.loadPrintState(); 
		this.rootPanel = rp;
		
		RootPanel.getBodyElement().getStyle().setOverflow(Overflow.VISIBLE);
		rootPanel.setStyleName("");
		
		printModePanel = new SimplePanel();
		
		Util.addRequiredPackage(Util.Package.ESRI_LAYERS_OSM);
		Util.addRequiredPackage(Util.Package.ESRI_DIJIT_SCALEBAR);
		Util.addEsriLoadHandler(new Runnable() {
			@Override
			public void run() {
				
				rootPanel.add(printModePanel);
				Util.debugObject("mapState", mapState);
				
				if( mapState.getSelectedBasemap().contentEquals("OSM") || !mapState.getSelectedBasemap().startsWith("http://") ){
					ArcGISTiledMapServiceLayer.Options options = ArcGISTiledMapServiceLayer.Options.create();
					options.setId(GisClient.BASEMAP_TOKEN+"tmpLayer");
					baseLayer = ArcGISTiledMapServiceLayer.create("http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer", options);	
				} else {
					baseLayer = ArcGISTiledMapServiceLayer.create(mapState.getSelectedBasemap());	
				}
				
				map = GisClient.createMap(baseLayer, new MapLoadHandler() {
					@Override
					public void onLoad() {
						
						if( mapState.getSelectedBasemap().contentEquals("OSM") ){
							map.addLayer(OpenStreetMapLayer.create());
							baseLayer.hide();
						} else if( !mapState.getSelectedBasemap().startsWith("http://") ) {
							BasemapGallery.INSTANCE.selectBasemap(mapState.getSelectedBasemap());
						}
						
						map.removeFromParent();
						map.getElement().getStyle().setVisibility(Visibility.VISIBLE);
						
						printModePanel.setWidth("700px");

						onPrintPageReady(map, printModePanel, mapState);
						
						map.resize();
						map.reposition();
					}
				});
				DataManager.INSTANCE.setMap(map);
				BasemapGallery.INSTANCE.setMap(map);
				map.getElement().getStyle().setVisibility(Visibility.HIDDEN);
				printModePanel.add(map);
				
			}
		});
	
	}
	
	private FlowPanel contentList = new FlowPanel();
	public Widget addVisibleLegends() {
		
		contentList.setWidth("700px");

		for( DataLayer dl: DataManager.INSTANCE.getDataLayers()  ){
			if( dl.getType() == DataLayerType.KML ) {
				
				contentList.add(new FeatureLayerLegendPanel(dl));
				
			} else if ( dl.getType() == DataLayerType.MapServer ) {
				
				dl.addLoadHandler(new DataLayerLoadHandler(){
					@Override
					public void onDataLoaded(DataLayer dl) {
						
						VerticalPanel panel = new VerticalPanel();
						panel.add(new HTML(dl.getLabel()));
						
						FlowPanel legends = new FlowPanel();
						legends.getElement().getStyle().setProperty("border", "1px solid #cccccc");
						legends.getElement().getStyle().setPadding(5, Unit.PX);
						legends.getElement().getStyle().setMargin(5, Unit.PX);
						panel.add(legends);
						
						MapServerDataLayer msdl = (MapServerDataLayer) dl;
						JsArray<LayerInfo> layers = msdl.getLegendInfo();
						for( int i = 0; i < layers.length(); i++ ){
							
							boolean crunch = false;
							if( msdl.legendIsGradient() ) crunch = true;
							LegendPanel legendPanel = new LegendPanel(msdl, crunch, layers.get(i).getMinScale(), layers.get(i).getMaxScale());

							legendPanel.setLayerTitle(layers.get(i).getName());
							
							if( layers.get(i).hasLegendInfo() ) {
								JsArray<LegendInfo> legendInfo = layers.get(i).getLegendInfo();
								for( int j = 0; j < legendInfo.length(); j++ ){
									LegendInfo li = legendInfo.get(j);
									legendPanel.addLayerElement(li,layers.get(i), j);
								}
							}
							
							legendPanel.setSubLayerData( msdl.getSubLayerData() );
							
							legends.add(legendPanel);
						}
						
						contentList.add(panel);
						
					}
				});
				
			}
		}
		
		return contentList;
	}
	
	public void addVisibleLayers() {
		JsArray<JavaScriptObject> datalayers = mapState.getDataLayers();
		for( int i = 0; i < datalayers.length(); i++ ) {
			JavaScriptObject jso = mapState.getDataLayers().get(i);
			if( ClientStateManager.isDatalayerKml(jso) ) {
				KmlOverlay kml = (KmlOverlay) jso;
				if( kml.isVisible() ){
					DataManager.INSTANCE.addDataLayer(new KmlDataLayer(kml));
				}
			} else if ( ClientStateManager.isDatalayerMapServer(jso) ) {
				MapServerOverlay mapServer = (MapServerOverlay) jso;
				if( mapServer.isVisible() ) {
					DataManager.INSTANCE.addDataLayer(new MapServerDataLayer(mapServer));
				}
			}
		}
	}
	
	public abstract void onPrintPageReady(MapWidget map, SimplePanel rootPanel, MapStateOverlay mapState);
	
	public void onPrintIconClick(MapWidget map) {
		String url = Window.Location.getHref();
		
		if( url.contains("?") )url += "&mode=print";
		else url += "?mode=print";
		
		ClientStateManager.savePrintState();
		
		if( handler != null ) url += "&"+handler.getAdditionalAttributes();
		
		Window.open(url, "_blank", "menubar=yes,location=yes,resizable=yes,scrollbars=yes,status=no");
	}	
	
}
